\documentclass[10pt,a4paper]{article}
\usepackage{polski}
\usepackage[utf8]{inputenc}
\usepackage{a4wide}
\usepackage{fancyhdr}
\usepackage{graphicx}
\pagestyle{fancy}
\lhead{}
\chead{Architektura aplikacji Kino}
\rhead{Strona \thepage}
\lfoot{}
\cfoot{}
\rfoot{}
\renewcommand\refname{Dokumenty}
\renewcommand{\headrulewidth}{0.4pt}
\def\thesection{\arabic{section}.}
\def\thesubsection{\thesection\arabic{subsection}.}
\def\thesubsubsection{\thesubsection\arabic{subsubsection}.}

\title{{\LARGE\textbf{Projekt Kino}}\\ \large{Architektura aplikacji Kino}}
\author{Paweł Chwała, Jacek Fiedorowicz, Piotr Kieć}

\begin{document}
\maketitle
\vfill
\nopagebreak
\begin{flushleft}
	\begin{tabular}{||c|c|c|l||}\hline
	\multicolumn{4}{|c|}{\textbf{Spis wersji}}\\ \hline\hline
	\textbf{Data} & \textbf{Wersja} & \textbf{Autor} & \textbf{Opis wprowadzonych zmian dokumentu}\\ \hline
 28.01.2010 & 1.0 & Paweł Chwała & utworzenie i edycja dokumentu \\ \hline
	\end{tabular}
\end{flushleft}

\thispagestyle{empty}
\newpage
\thispagestyle{empty}
\tableofcontents
\newpage


\section{Wstęp}
\subsection{Cel opracowania dokumentu architektury oprogramowania}
\noindent Dokument architektury oprogramowania jest jednym z podstawowych dokumentów otrzymywanych w fazie projektowania zgodnie z metodyką RUP. Pełni szczególnie ważną rolę dla zespołu programistów -- jest zbiorem ich ustaleń na temat architektury oprogramowania. Dokument architektury to pozycja po którą powinien sięgać programista w przypadku jakichkolwiek wątpliwości co do budowy i funkcjonowania aplikacji. Dokument pełni też ważną rolę dla klienta -- jest świadectwem kompromisu programistów, dotyczącego funkcjonowaia oprogramowania. Ponadto dokument architektury stanowi dla klienta dokumentację.
\subsection{Zakres opracowania dokumentu architektury oprogramowania}
\noindent Dokument architektury oprogramowania jest tylko deklaracją. Nie należy zakładać, że dokument ten wyczerpująco wyjaśni wszystkie kwestie zwiazane z architekturą oprogramowania. Poruszone w nim tematy dotyczą jedynie podstawowych problemów architektury oprogramowania.
\section{Opis elementów architektury oprogramowania}
\noindent Ponieważ aplikacja Kino jest stroną internetową pracującą po stronie serwera w niniejszym rozdziale zostaną po krótce opisane takie elementy jak: serwer, baza danych, pliki konfiguracyjne, pliki źródłowe oraz interfejs użytkownika.
\subsection{Serwer}
\noindent Serwer jest kluczowym elementem architektury. Bez jego obecności niemożliwa jest instalacja i funkcjonowanie aplikacji Kino. Oprócz samej obecności serwera, wymaga się aby zainstalowane zostało, niezbędne do pracy aplikacji Kino, oprogramowanie. Mówiąc niezbędne oprogramowanie mamy na myśli oprogramowanie napomniane na poniższej liście:
\begin{itemize}
	\item Serwer HTTP -- Apache 2.1
    \item System zarządzania bazami danych -- PostgreSQL 8.3
    \item Interpreter języka PHP
    \item Moduł dla serwera Apache dodający obsługę skryptów PHP
\end{itemize}
\subsection{Baza danych}
\noindent Po stronie serwera zainstalowany zostanie system do zarządzanai bazami danych PostgreSQL. Będzie on administrował bazą danych aplikacji Kino. Programiści zaprojektowali model danych i na jego podstawie stworzyli bazę danych. Ze względu na czytelne komentarze w skrypcie tworzącym bazę danych zdecydowaliśmy się go tu zacytować zamiast powielać naszą pracę i objaśniać poszczególne tabele bazy danych. W bazie danych zamodelowane zostały tabele odpowiedzialne za przechowywanie użytkowników, wydarzeń, filmów, seansów, zapisów, sal kinowych oraz rezerwacji. Zamieszczenie gotowego schematu zamiast modelu konceptualnego ma taką zaletę, że w dokumencie architektury programiści przeczytają jak wygląda schemat bazy danych, nazwy poszczególnych tabel i atrybutów w systmie zarządzania bazami danych PostgreSQL. Schemat bazy danych dodajemy za pomocą polecenia:
\begin{verbatim}
    psql -f schemat.sql
\end{verbatim}

\noindent Schemat bazy danych:

\small{
\begin{verbatim}
-- usuwamy schemat kino
DROP SCHEMA kino CASCADE;

-- tworzymy schemat kino
CREATE SCHEMA kino;  

-- przenosimy sie do schematu kino
SET search_path TO kino;


-- -- -- -- -- -- -- -- --
-- tworzymy baze danych --
-- -- -- -- -- -- -- -- --


-- tworzymy sekwencje:

-- tworzymy sekewencje dla tabeli uzytkownik
CREATE SEQUENCE uzytkownik_seq START 1; 

-- tworzymy sekwencje dla tabeli film
CREATE SEQUENCE film_seq START 1;

-- tworzymy sekwencje dla tabeli wydarzenie
CREATE SEQUENCE wydarzenie_seq START 1;

-- tworzymy sekwencje dla tabeli sala_kinowa
CREATE SEQUENCE sala_kinowa_seq START 1;

-- tworzymy sekwencje dla tabeli seans
CREATE SEQUENCE seans_seq START 1;

-- tworzymy sekwenceje dla tabeli zapis
CREATE SEQUENCE zapis_seq START 1;

-- tworzymy sekwencje dla tabeli rezerwacja 
CREATE SEQUENCE rezerwacja_seq START 1;


-- tworzymy tabele podstawowe:

-- tworzymy tabele uzytkownik
CREATE TABLE uzytkownik (
   idu               int DEFAULT nextval ('uzytkownik_seq'),   -- identyfikator uzytkownika
   imie              varchar (80) NOT NULL,                    -- imie uzytkownika
   nazwisko          varchar (100) NOT NULL,                   -- nazwisko uzytkownika
   email             varchar (100) NOT NULL,                   -- adres email uzytkownika
   nr_tel            text NOT NULL,                            -- nr telefonu uzytkownika
   login             varchar (80) NOT NULL,                    -- login uzytkownika
   haslo             text NOT NULL,                            -- haslo uzytkownika
   typ               char NOT NULL DEFAULT 'u',                -- typ uzytkownika
   data_ur           date NOT NULL,                            -- data urodzenia uzytkownika
   
   PRIMARY KEY (idu),
   
   UNIQUE (login),
   CONSTRAINT poprawny_typ CHECK (typ IN ('a', 'u', 'd'))
);

-- tworzymy tabele film
CREATE TABLE film (
   idf               int DEFAULT nextval ('film_seq'),  -- identyfikator filmu
   tytul             text NOT NULL,                     -- tytul filmu
   rezyser           text,                              -- rezyser filmu
   gatunek           text,                              -- gatunek filmu
   opis              text,                              -- opis filmu
   kategoria_wiekowa int NOT NULL,                      -- kategoria wiekowa
   dlugosc           int DEFAULT 0,                     -- dlugosc filmu
   data_premiery     date,                              -- data premiery filmu
   
   PRIMARY KEY (idf),

   CONSTRAINT poprawna_kategoria CHECK (kategoria_wiekowa >= 0)
);

-- towrzymy tabele wydarzenie
CREATE TABLE wydarzenie (
   idw               int DEFAULT nextval ('wydarzenie_seq'),  -- identyfikator wydarzenia
   nazwa             text NOT NULL,                           -- nazwa wydarzenia
   data              timestamp NOT NULL,                      -- data wydarzenia
   opis              text,                                    -- opis wydarzenia
   ilosc_miejsc      int NOT NULL,                            -- ilosc miejsc 
   kategoria_wiekowa int DEFAULT 0 NOT NULL,                  -- kategoria wiekowa
   
   PRIMARY KEY (idw),

   CONSTRAINT poprawna_ilosc CHECK (ilosc_miejsc > 0),
   CONSTRAINT poprawna_kategoria CHECK (kategoria_wiekowa >= 0)
);

-- tworzymy tabele sala_kinowa
CREATE TABLE sala_kinowa (
   nr_sali           int DEFAULT nextval ('sala_kinowa_seq'), -- nr sali kinowej
   dlugosc           int NOT NULL,                            -- ilosc rzedow
   szerokosc         int NOT NULL,                            -- ilosc krzesel w rzedzie
-- liczba_miejsc     int DEFAULT (dlugosc * szerokosc),       -- ilosc miejsc
   
   PRIMARY KEY (nr_sali),

   CONSTRAINT poprawny_rozmiar CHECK (dlugosc > 0 AND szerokosc > 0)
);


-- tworzymy tabele dodatkowe:

-- tworzymy tabele seans
CREATE TABLE seans (
   ids               int DEFAULT nextval ('seans_seq'),  -- identyfikator seansu
   idf               int NOT NULL,                       -- identyfikator filmu
   nr_sali           int NOT NULL,                       -- nr sali
   data              timestamp NOT NULL,                 -- data seansu
   cena              int NOT NULL,                       -- cena seansu

   PRIMARY KEY (ids),

   FOREIGN KEY (idf) REFERENCES film (idf),
   FOREIGN KEY (nr_sali) REFERENCES sala_kinowa (nr_sali),

   CONSTRAINT poprawna_cena CHECK (cena >= 0)
);

-- tworzymy tabele zapis
CREATE TABLE zapis (
   idz               int DEFAULT nextval ('zapis_seq'),  -- identyfikator zapisu
   idu               int NOT NULL,                       -- identyfikator uzytkownika
   idw               int NOT NULL,                       -- identyfikator wydarzenia
   data_zapisu       timestamp NOT NULL,                 -- data zapisu
   
   PRIMARY KEY (idz),
   
   FOREIGN KEY (idu) REFERENCES uzytkownik (idu),
   FOREIGN KEY (idw) REFERENCES wydarzenie (idw)
);

-- tworzymy tabele rezerwacja
CREATE TABLE rezerwacja (
   idr               int DEFAULT nextval ('rezerwacja_seq'), -- identyfikator rezerwacji
   idu               int NOT NULL,                           -- identyfikator uzytkownika
   ids               int NOT NULL,                           -- identyfikator seansu
   data_rezerwacji   timestamp NOT NULL,                     -- data rezerwacji
   miejsca           point NOT NULL,                         -- miejsce rezerwacji
   dostepnosc        char NOT NULL DEFAULT 'd',              -- czy zrealizowana
   
   PRIMARY KEY (idr),

   FOREIGN KEY (idu) REFERENCES uzytkownik (idu),
   FOREIGN KEY (ids) REFERENCES seans (ids),
   CONSTRAINT poprawna_dostepnosc CHECK (dostepnosc IN ('d','n'))
);

-- tworzymy funkcje i wyzwalacze:

-- sprawdzanie czy data urodzenia uzytkownika jest poprawna
CREATE FUNCTION sprawdz_date_ur () RETURNS trigger AS $$
BEGIN
   IF NEW.data_ur <= 'now' THEN
      RETURN NEW;
   ELSE
      RAISE EXCEPTION '% % ma date urodzenia w przyszlosci!', NEW.imie, NEW.nazwisko;
      RETURN NULL;
   END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER poprawna_data_ur BEFORE UPDATE OR INSERT ON uzytkownik
    FOR EACH ROW EXECUTE PROCEDURE sprawdz_date_ur ();

-- sprawdzanie czy data zapisu jest poprawna
CREATE FUNCTION sprawdz_date_zapisu () RETURNS trigger AS $$
BEGIN
   IF NEW.data_zapisu <= 'now' THEN
      RETURN NEW;
   ELSE
      RAISE EXCEPTION 'Zapis % jest niepoprawny - jego data jest w przyszlosci', NEW.idz;
      RETURN NULL;
   END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER poprawna_data_zapisu BEFORE UPDATE OR INSERT ON zapis
    FOR EACH ROW EXECUTE PROCEDURE sprawdz_date_zapisu ();


-- sprawdzanei kategori wiekowej
CREATE FUNCTION sprawdz_kategorie () RETURNS trigger AS $$
DECLARE
   k  integer;
   du date;
BEGIN
   SELECT film.kategoria_wiekowa INTO k FROM film 
        WHERE film.idf = (SELECT seans.idf FROM seans WHERE ids = NEW.ids);
   SELECT uzytkownik.data_ur INTO du FROM uzytkownik WHERE uzytkownik.idu = NEW.idu;
   IF  (EXTRACT (YEAR FROM date ('now')) <= k + EXTRACT (YEAR FROM du)) THEN  
      RAISE EXCEPTION 'Uzytkownik nie miesci sie w  kategori wiekowej!';
      RETURN NULL;
   ELSE
      RETURN NEW;
   END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER a BEFORE INSERT ON rezerwacja 
    FOR EACH ROW EXECUTE PROCEDURE sprawdz_kategorie ();

-- -- -- -- -- -- -- --
-- wypelnianie bazy  --
-- -- -- -- -- -- -- --

-- wypelnianie tabeli uzytkownik
INSERT INTO uzytkownik (imie, nazwisko, email, nr_tel, login, haslo, typ, data_ur)
    VALUES
        ('Paweł',
         'Chwała', 
         'pawel.chwala@gmail.com', 
         '+48796249252',
         'admin', 
         'tajne', 
         'a', 
         '1987-04-02');
\end{verbatim}}

\noindent Aplikacja Kino do prawidłowego funkcjonowania wymaga bazy danych stworzonej za pomocą powyższego schematu lub schematu, który powyższy rozszerza. Schemat dodajemy za pomocą polecenia wymienionego przed treścią schematu.

\subsection{Pliki konfiguracyjne}
\noindent Aplikacja Kino posiada jeden plik konfiguracyjny zapisany w formacie XML, w którym umieszczone są informacje dotyczące połączenia z bazą danych. Nie ma konieczności przechowywania innej konfiguracji.
\subsection{Pliki źródłowe}
\noindent Aplikacja Kino pisana będzie z wykorzystaniem wzorca projektowego Model -- Widok -- Kontroler. W związky z tym logicznym wydaje się podział plików źródłowych na trzy kategorie:
\begin{itemize}
    \item Pliki źródłowe z kodem PHP odpowiedzialne za połączenie z bazą danych i modelowanie danych.
    \item Pliki źródłowe z kodem PHP odpowiedzialne za generowanie wyglądu strony na podstawie modelu danych oraz plików odpowiedzialnych za generowanie interfejsu graficznego.
    \item Pliki źródłowe z kodem HTML odpowiedzialne za generowanie interfejsu graficznego.
\end{itemize}
\subsection{Interfejs użytkownika}
\noindent Graficzny interfejs użytkownika został opisanay w osobnym dokumencie \cite{gui}. Należy wspomnieć, iż interfejs zostanie opracowany w oparciu o język HTML i technologie takie jak CSS i JavaScript.
%\section{Perspektywa logiczna}
%\section{Perspektywa implementacyjna}
%\section{Perspektywa procesowa}
\section{Perspektywa wdrożeniowa}
\noindent Wdrożenie aplikacji Kino wymaga obecności serwera oraz wykonania następujących czynności:
\begin{itemize}
    \item instalacji i konfiguracji serwera Apache
    \item instalacji i konfiguracji interpretera języka PHP
    \item instalacji i konfiguracji modłuły pozwalającego na obsługe skryptów PHP po stronie serwera Apache
    \item instalacji i konfiguracji systemu zarządzania bazami danych PostgreSQL
    \item stworzenia bazy danych na podstawie schematu bazy danych umieszczonego w dziale dotyczącym bazy danych
    \item umieszczenie na serwerze plików źródłowych aplikacji 
    \item stworzenie konfiguracji
\end{itemize}
\section{Możliwości rozwoju}
\noindent Dzięki zastosowaniu wzorca Model--Widok--Kontroler programiści budują sobie wygodne środowisko nadające się do dalszego rozwoju i wdrażania kolejnych funkcjonalności. Przyjęcie przez programistów wspólnego standardu kodowania (opisanego w dokumencie \cite{standardy}).

\newpage
\begin{thebibliography}{2}
	\bibitem{gui}
		Paweł Chwała, Jacek Fiedorowicz, Piotr Kieć, 
		\emph{Projekt graficznego interfejsu użytkownika}.
	\bibitem{standardy}
		Paweł Chwała, Jacek Fiedorowicz, Piotr Kieć,
		\emph{Standardy}.
\end{thebibliography}


\end{document}
